home *** CD-ROM | disk | FTP | other *** search
/ ftp.mactech.com 2010 / ftp.mactech.com.tar / ftp.mactech.com / machack / Hacks95 / MacsBugTV.sit / MacsBug TV / Sources / MTVdcmd.c next >
Text File  |  1995-06-24  |  29KB  |  1,059 lines

  1. /*
  2.     File:        MTVdcmd.c
  3.  
  4.     Contains:    MacsBug TV debugger command
  5.  
  6.     Written by:    Chris Wysocki
  7.  
  8.     Copyright:    © 1995 Christopher R. Wysocki. All rights reserved.
  9.  
  10.     Change History (most recent first):
  11.  
  12.                  6/24/95    crw        Added top and left options
  13.                  6/22/95    crw        Got it finally working
  14.                  5/20/95    crw        New today
  15.  
  16.     Notes:
  17.         - requires Quadra/Power Mac AV video card (Civic)
  18.  
  19. */
  20.  
  21. //====================================================================================================
  22. //    Includes
  23. //====================================================================================================
  24.  
  25. #if applec && mc68000
  26. #pragma load "MTVdcmd.dump"
  27. #endif
  28.  
  29. #define    SystemSevenOrLater        1
  30.  
  31. #include <Types.h>
  32. #include <Devices.h>
  33. #include <Gestalt.h>
  34. #include <LowMem.h>
  35. #include <Memory.h>
  36. #include <TextUtils.h>
  37. #include <PLStringFuncs.h>
  38.  
  39. #include "dcmd.h"
  40. #include "put.h"
  41.  
  42. #undef    Version3dcmd
  43.  
  44. #include "MTVdcmd.h"
  45.  
  46. //====================================================================================================
  47. //    Constants
  48. //====================================================================================================
  49.  
  50. #define    kMacsBugMaxWidth        640                    //    maximum width of MacsBug display
  51. #define    kMacsBugMaxHeight        480                    //    maximum height of MacsBug display
  52.  
  53. #define    kDefaultVideoWidth        160                    //    default width of video display
  54. #define    kDefaultVideoHeight        120                    //    default height of video display
  55. #define    kMinimumVideoWidth        0                    //    minimum width of video display
  56. #define    kMinimumVideoHeight        0                    //    minimum height of video display
  57. #define    kMaximumVideoWidth        640                    //    maximum width of video display
  58. #define    kMaximumVideoHeight        480                    //    maximum height of video display
  59.  
  60. #define    kDcmdVersion            ((kDcmdMajorVersion << 24L)    |    \
  61.                                  (kDcmdMinorVersion << 16L)    |    \
  62.                                  (kDcmdStage << 8L)            |    \
  63.                                  (kDcmdNonRelRev))
  64. #define    kDcmdNameStr            "MTV"
  65. #define    kDcmdUsageStr            "option [option…]"
  66. #define    kDcmdCreditsStr            "Chris Wysocki/MacHack 1995 - built " __DATE__ " at " __TIME__
  67.  
  68. #define    kCivic68KBaseAddr        0x50036000            //    Civic base address
  69. #define    kSebas68KAddrReg        0x50F30000            //    Sebastian address register
  70. #define    kSebas68KDataReg        0x50F30010            //    Sebastian data register
  71. #define    kSebas68KCLUT            0x50F30020            //    Sebastian color lookup table
  72. #define    kCivicPPCBaseAddr        0xE0036000            //    Civic base address
  73. #define    kSebasPPCAddrReg        0xE0F30000            //    Sebastian address register
  74. #define    kSebasPPCDataReg        0xE0F30010            //    Sebastian data register
  75. #define    kSebasPPCCLUT            0xE0F30020            //    Sebastian color lookup table
  76.  
  77. #define    csCivicSetVidInRect        138                    //    Control csCode for Civic video driver
  78.  
  79. enum {                                                //    error result codes
  80.     errMTVSyntaxError = -10000,                        //    command syntax error
  81.     errMTVUnknownOption = -10001,                    //    unknown command line option
  82.     errMTVFeatureNotImplemented = -10002,            //    specified feature is not implemented
  83.     errMTVHardwareNotAvailable = -10003,            //    required hardware is not available
  84.     errMTVValueOutOfRange = -10004                    //    specified value is out of range
  85. };
  86.  
  87. //====================================================================================================
  88. //    Type Definitions
  89. //====================================================================================================
  90.  
  91. struct VDVidInRect                                    //    for csCivicSetVidInRect to Civic video driver
  92. {
  93.     Rect                    csRect;                    //    set to playthrough rectangle in global coordinates
  94.     short                    csPage;                    //    always 0
  95.     long                    csBaseAddr;                //    always $98765432 (ignored?)
  96. };
  97.  
  98. typedef struct VDVidInRect VDVidInRect;
  99.  
  100. struct CLUTEntry
  101. {
  102.     unsigned char            red;                    //    red component
  103.     unsigned char            green;                    //    green component
  104.     unsigned char            blue;                    //    blue component
  105.     unsigned char            alpha;                    //    alpha channel
  106. };
  107.  
  108. typedef struct CLUTEntry CLUTEntry, *CLUTEntryPtr;
  109.  
  110. //====================================================================================================
  111. //    Global Variables
  112. //====================================================================================================
  113.  
  114. Boolean                    gIsPowerPC;                    //    true if running on PowerPC
  115. Boolean                    gHasCivic;                    //    true if Civic video hardware is present
  116. Boolean                    gHasValkyrie;                //    true if Valkyrie video hardware is present
  117. Boolean                    gHasTVTuner;                //    true if Valkyrie TV tuner is present
  118. Boolean                    gPlaythroughOn;                //    true if video playthough is enabled
  119. short                    gCivicRefNum;                //    refnum of Civic video driver
  120. short                    gValkyrieRefNum;            //    refnum of Valkyrie video driver
  121. Rect                    gVideoRect;                    //    playthrough rectangle in global coordinates
  122. Ptr                        gCivicBaseAddr;                //    base address of Civic chip, if present
  123. Ptr                        gSebasAddrReg;                //    address of Sebastian address register, if present
  124. Ptr                        gSebasDataReg;                //    address of Sebastian address register, if present
  125. Ptr                        gSebasCLUT;                    //    address of Sebastian CLUT, if present
  126.  
  127. //====================================================================================================
  128. //    Inline Functions
  129. //====================================================================================================
  130.  
  131. pascal void NOP(void) = { 0x4E71 };
  132.  
  133. //====================================================================================================
  134. //    Prototypes
  135. //====================================================================================================
  136.  
  137. static void HandleDcmdInit(dcmdBlock *paramPtr);
  138. static void HandleDcmdSecondaryInit(dcmdBlock *paramPtr);
  139. static void HandleDcmdShutdown(dcmdBlock *paramPtr);
  140. static void HandleDcmdHelp(dcmdBlock *paramPtr);
  141. static void HandleDcmdGetInfo(dcmdBlock *paramPtr);
  142. static void HandleDcmdDoIt(dcmdBlock *paramPtr);
  143.  
  144. static OSErr TurnVideoOn(void);
  145. static OSErr TurnVideoOff(void);
  146. static OSErr SetVideoSize(long size);
  147. static OSErr SetVideoLeft(long left);
  148. static OSErr SetVideoTop(long top);
  149. static OSErr SetVideoWidth(long width);
  150. static OSErr SetVideoHeight(long height);
  151. static void SetVideoPlaythrough(Boolean on);
  152. static OSErr SetVideoRectangle(const Rect *videoRect);
  153. static OSErr SetTVChannel(long channel);
  154.  
  155. static OSErr DumpCLUT(void);
  156. static void ReadCivicCLUTEntry(unsigned char index, CLUTEntryPtr entry);
  157. static void WriteCivicCLUTEntry(unsigned char index, const CLUTEntryPtr entry);
  158.  
  159. static short GetDriverRefNum(const StringPtr driverName);
  160.  
  161.  
  162. //====================================================================================================
  163. //
  164. //    Routine:        CommandEntry
  165. //
  166. //    Description:    Main entry point for dcmd
  167. //
  168. //    Parameters:        paramPtr    - pointer to dcmd paramter block
  169. //
  170. //    Returns:        nothing
  171. //
  172. //====================================================================================================
  173.  
  174. pascal void
  175. CommandEntry(dcmdBlock *paramPtr)
  176. {
  177.     switch (paramPtr->request)
  178.     {
  179.         case dcmdInit:
  180.             HandleDcmdInit(paramPtr);
  181.             break;
  182.  
  183.         case dcmdSecondaryInit:
  184.             HandleDcmdSecondaryInit(paramPtr);
  185.             break;
  186.  
  187.         case dcmdShutdown:
  188.             HandleDcmdShutdown(paramPtr);
  189.             break;
  190.  
  191.         case dcmdHelp:
  192.             HandleDcmdHelp(paramPtr);
  193.             break;
  194.  
  195.         case dcmdGetInfo:
  196.             HandleDcmdGetInfo(paramPtr);
  197.             break;
  198.  
  199.         case dcmdDoIt:
  200.             HandleDcmdDoIt(paramPtr);
  201.             break;
  202.     }
  203. }
  204.  
  205.  
  206. //====================================================================================================
  207. //
  208. //    Routine:        HandleDcmdInit
  209. //
  210. //    Description:    Handle a dcmdInit call
  211. //
  212. //    Parameters:        paramPtr    - pointer to dcmd paramter block
  213. //
  214. //    Returns:        nothing
  215. //
  216. //====================================================================================================
  217.  
  218. static void
  219. HandleDcmdInit(dcmdBlock *paramPtr)
  220. {
  221. #pragma unused (paramPtr)
  222.     long                response;
  223.     GDHandle            mainDeviceH;
  224.     Rect *                gdRect;
  225.     short                hOffset;
  226.     short                vOffset;
  227.  
  228.     gIsPowerPC = ((Gestalt(gestaltSysArchitecture, &response) == noErr) && (response == gestaltPowerPC));
  229.     gCivicRefNum = GetDriverRefNum("\p.Display_Video_Apple_Civic");
  230.     gHasCivic = (gCivicRefNum != 0);
  231.     gHasValkyrie = false;                            //    to be added
  232.     gHasTVTuner = false;                            //    to be added
  233.     gPlaythroughOn = false;
  234.  
  235.     if (gHasCivic)
  236.     {
  237.         if (gIsPowerPC)
  238.         {
  239.             gCivicBaseAddr = (Ptr) kCivicPPCBaseAddr;
  240.             gSebasAddrReg = (Ptr) kSebasPPCAddrReg;
  241.             gSebasDataReg = (Ptr) kSebasPPCDataReg;
  242.             gSebasCLUT = (Ptr) kSebasPPCCLUT;
  243.         }
  244.         else
  245.         {
  246.             gCivicBaseAddr = (Ptr) kCivic68KBaseAddr;
  247.             gSebasAddrReg = (Ptr) kSebas68KAddrReg;
  248.             gSebasDataReg = (Ptr) kSebas68KDataReg;
  249.             gSebasCLUT = (Ptr) kSebas68KCLUT;
  250.         }
  251.     }
  252.     
  253.     mainDeviceH = LMGetMainDevice();                //    get handle to main screen device
  254.     gdRect = &(**mainDeviceH).gdRect;
  255.     hOffset = ((gdRect->right - gdRect->left) - kMacsBugMaxWidth) / 2;
  256.     if (hOffset < 0) hOffset = 0;
  257.     vOffset = ((gdRect->bottom - gdRect->top) - kMacsBugMaxHeight) / 2;
  258.     if (vOffset < 0) vOffset = 0;
  259.     gVideoRect.top = gdRect->top + vOffset;
  260.     gVideoRect.left = gdRect->right - hOffset - kDefaultVideoWidth;
  261.     gVideoRect.bottom = gVideoRect.top + kDefaultVideoHeight;
  262.     gVideoRect.right = gVideoRect.left + kDefaultVideoWidth;
  263. }
  264.  
  265.  
  266. //====================================================================================================
  267. //
  268. //    Routine:        HandleDcmdSecondaryInit
  269. //
  270. //    Description:    Handle a dcmdSecondaryInit call (new with format 3 dcmds)
  271. //
  272. //    Parameters:        paramPtr    - pointer to dcmd paramter block
  273. //
  274. //    Returns:        nothing
  275. //
  276. //====================================================================================================
  277.  
  278. static void
  279. HandleDcmdSecondaryInit(dcmdBlock *paramPtr)
  280. {
  281. #pragma unused (paramPtr)
  282. }
  283.  
  284.  
  285. //====================================================================================================
  286. //
  287. //    Routine:        HandleDcmdShutdown
  288. //
  289. //    Description:    Handle a dcmdShutdown call (new with format 3 dcmds)
  290. //
  291. //    Parameters:        paramPtr    - pointer to dcmd paramter block
  292. //
  293. //    Returns:        nothing
  294. //
  295. //====================================================================================================
  296.  
  297. static void
  298. HandleDcmdShutdown(dcmdBlock *paramPtr)
  299. {
  300. #pragma unused (paramPtr)
  301. }
  302.  
  303.  
  304. //====================================================================================================
  305. //
  306. //    Routine:        HandleDcmdHelp
  307. //
  308. //    Description:    Handle a dcmdHelp call
  309. //
  310. //    Parameters:        paramPtr    - pointer to dcmd paramter block
  311. //
  312. //    Returns:        nothing
  313. //
  314. //====================================================================================================
  315.  
  316. static void
  317. HandleDcmdHelp(dcmdBlock *paramPtr)
  318. {
  319. #pragma unused (paramPtr)
  320. #if !Version3dcmd
  321.     dcmdDrawLine("\p" kDcmdNameStr " " kDcmdUsageStr);
  322.     dcmdDrawLine("\p   The MacsBug TV dcmd - for Quadra and Power Macintosh AVs");
  323. #endif
  324.     dcmdDrawLine("\p   Options:");
  325.     dcmdDrawLine("\p      on          - turn video input on");
  326.     dcmdDrawLine("\p      off         - turn video input off");
  327.     dcmdDrawLine("\p      s[ize] n    - set video size [1/2/4 for full/half/quarter size]");
  328.     dcmdDrawLine("\p      t[op] n     - set video top coordinate");
  329.     dcmdDrawLine("\p      l[eft] n    - set video left coordinate");
  330.     dcmdDrawLine("\p      w[idth] n   - set video width");
  331.     dcmdDrawLine("\p      h[eight] n  - set video height");
  332.     if (gHasTVTuner)
  333.         dcmdDrawLine("\p      ch[annel] n - select TV channel n");
  334. #if !Version3dcmd
  335.     dcmdDrawLine("\p   (" kDcmdCreditsStr ")");
  336. #endif
  337. }
  338.  
  339.  
  340. //====================================================================================================
  341. //
  342. //    Routine:        HandleDcmdGetInfo
  343. //
  344. //    Description:    Handle a dcmdGetInfo call (new with format 3 dcmds)
  345. //
  346. //    Parameters:        paramPtr    - pointer to dcmd paramter block
  347. //
  348. //    Returns:        nothing
  349. //
  350. //====================================================================================================
  351.  
  352. static void
  353. HandleDcmdGetInfo(dcmdBlock *paramPtr)
  354. {
  355. #if !Version3dcmd
  356. #pragma unused (paramPtr)
  357. #else
  358.     dcmdFillVersion(paramPtr, kDcmdVersion);
  359.     dcmdFillString(paramPtr, usageStr, "\p" kDcmdUsageStr);
  360.     dcmdFillString(paramPtr, creditsStr, "\p" kDcmdCreditsStr);
  361. #endif
  362. }
  363.  
  364.  
  365. //====================================================================================================
  366. //
  367. //    Routine:        HandleDcmdDoIt
  368. //
  369. //    Description:    Handle a dcmdDoIt call
  370. //
  371. //    Parameters:        paramPtr    - pointer to dcmd paramter block
  372. //
  373. //    Returns:        nothing
  374. //
  375. //====================================================================================================
  376.  
  377. #define    CR        0x0D
  378.  
  379. static void
  380. HandleDcmdDoIt(dcmdBlock *paramPtr)
  381. {
  382. #pragma unused (paramPtr)
  383.     Boolean                ok;
  384.     short                delim;
  385.     long                value;
  386.     Str255                option;
  387.     OSErr                err = noErr;
  388.  
  389.     dcmdSwapWorlds();
  390.  
  391.     do
  392.     {
  393.         delim = dcmdGetNextParameter(option);
  394.  
  395.         if (PLstrcmp(option, "\pon") == 0)
  396.         {
  397.             err = TurnVideoOn();
  398.             if (err == noErr)
  399.                 dcmdDrawLine("\pVideo turned on");
  400.             else
  401.                 dcmdDrawLine("\pUnable to turn video on");
  402.         }
  403.         else if (PLstrcmp(option, "\poff") == 0)
  404.         {
  405.             err = TurnVideoOff();
  406.             if (err == noErr)
  407.                 dcmdDrawLine("\pVideo turned off");
  408.             else
  409.                 dcmdDrawLine("\pUnable to turn video off");
  410.         }
  411.         else if ((PLstrcmp(option, "\pt") == 0) || (PLstrcmp(option, "\ptop") == 0))
  412.         {
  413.             delim = dcmdGetNextExpression(&value, &ok);
  414.             if (ok)
  415.             {
  416.                 err = SetVideoTop(value);
  417.                 if (err == noErr)
  418.                 {
  419.                     PutPStr("\pVideo top coordinate changed to ");
  420.                     PutUDec(value);
  421.                 }
  422.                 else
  423.                     PutPStr("\pUnable to change video top coordinate");
  424.                 PutLine();
  425.             }
  426.             else
  427.             {
  428.                 err = errMTVSyntaxError;
  429.                 dcmdDrawLine("\pSyntax error");
  430.             }
  431.         }
  432.         else if ((PLstrcmp(option, "\pl") == 0) || (PLstrcmp(option, "\pleft") == 0))
  433.         {
  434.             delim = dcmdGetNextExpression(&value, &ok);
  435.             if (ok)
  436.             {
  437.                 err = SetVideoLeft(value);
  438.                 if (err == noErr)
  439.                 {
  440.                     PutPStr("\pVideo left coordinate changed to ");
  441.                     PutUDec(value);
  442.                 }
  443.                 else
  444.                     PutPStr("\pUnable to change video left coordinate");
  445.                 PutLine();
  446.             }
  447.             else
  448.             {
  449.                 err = errMTVSyntaxError;
  450.                 dcmdDrawLine("\pSyntax error");
  451.             }
  452.         }
  453.         else if ((PLstrcmp(option, "\ps") == 0) || (PLstrcmp(option, "\psize") == 0))
  454.         {
  455.             delim = dcmdGetNextExpression(&value, &ok);
  456.             if (ok)
  457.             {
  458.                 err = SetVideoSize(value);
  459.                 if (err == noErr)
  460.                 {
  461.                     PutPStr("\pVideo size changed to ");
  462.                     switch (value)
  463.                     {
  464.                         case 1:        PutPStr("\pfull");        break;    
  465.                         case 2:        PutPStr("\phalf");        break;
  466.                         case 3:        PutPStr("\pthird");        break;
  467.                         case 4:        PutPStr("\pquarter");    break;
  468.                     }
  469.                 }
  470.                 else
  471.                     PutPStr("\pUnable to change video size");
  472.                 PutLine();
  473.             }
  474.             else
  475.             {
  476.                 err = errMTVSyntaxError;
  477.                 dcmdDrawLine("\pSyntax error");
  478.             }
  479.         }
  480.         else if ((PLstrcmp(option, "\pw") == 0) || (PLstrcmp(option, "\pwidth") == 0))
  481.         {
  482.             delim = dcmdGetNextExpression(&value, &ok);
  483.             if (ok)
  484.             {
  485.                 err = SetVideoWidth(value);
  486.                 if (err == noErr)
  487.                 {
  488.                     PutPStr("\pVideo width changed to ");
  489.                     PutUDec(value);
  490.                 }
  491.                 else
  492.                     PutPStr("\pUnable to change video width");
  493.                 PutLine();
  494.             }
  495.             else
  496.             {
  497.                 err = errMTVSyntaxError;
  498.                 dcmdDrawLine("\pSyntax error");
  499.             }
  500.         }
  501.         else if ((PLstrcmp(option, "\ph") == 0) || (PLstrcmp(option, "\pheight") == 0))
  502.         {
  503.             delim = dcmdGetNextExpression(&value, &ok);
  504.             if (ok)
  505.             {
  506.                 err = SetVideoHeight(value);
  507.                 if (err == noErr)
  508.                 {
  509.                     PutPStr("\pVideo height changed to ");
  510.                     PutUDec(value);
  511.                 }
  512.                 else
  513.                     PutPStr("\pUnable to change video height");
  514.                 PutLine();
  515.             }
  516.             else
  517.             {
  518.                 err = errMTVSyntaxError;
  519.                 dcmdDrawLine("\pSyntax error");
  520.             }
  521.         }
  522.         else if ((PLstrcmp(option, "\pch") == 0) || (PLstrcmp(option, "\pchannel") == 0))
  523.         {
  524.             delim = dcmdGetNextExpression(&value, &ok);
  525.             if (ok)
  526.             {
  527.                 err = SetTVChannel(value);
  528.                 if (err == noErr)
  529.                 {
  530.                     PutPStr("\pChannel changed to ");
  531.                     PutUDec(value);
  532.                     PutLine();
  533.                 }
  534.                 else if (err == errMTVHardwareNotAvailable)
  535.                     dcmdDrawLine("\pTV tuner not present");
  536.                 else
  537.                     dcmdDrawLine("\pUnable to set channel");
  538.             }
  539.             else
  540.             {
  541.                 err = errMTVSyntaxError;
  542.                 dcmdDrawLine("\pSyntax error");
  543.             }
  544.         }
  545.         else if (PLstrcmp(option, "\pdc") == 0)
  546.         {
  547.             err = DumpCLUT();
  548.         }
  549.         else
  550.         {
  551.             err = errMTVUnknownOption;
  552.             dcmdDrawLine("\pUnknown option");
  553.         }
  554.  
  555.     } while ((err == noErr) && (delim != CR));
  556.     
  557.     dcmdSwapWorlds();
  558. }
  559.  
  560.  
  561. //====================================================================================================
  562. //
  563. //    Routine:        TurnVideoOn
  564. //
  565. //    Description:    Turn on the video
  566. //
  567. //    Parameters:        none
  568. //
  569. //    Returns:        error result code (negative) or noErr
  570. //
  571. //====================================================================================================
  572.  
  573. static OSErr
  574. TurnVideoOn()
  575. {
  576.     OSErr                err;
  577.     CLUTEntry            entry;
  578.  
  579.     if (gHasCivic)
  580.     {
  581.         SetVideoPlaythrough(false);                    //    disable playthrough
  582.  
  583.         ReadCivicCLUTEntry(0x7F, &entry);            //    select entry 0x7F (background color) as key color
  584.         entry.alpha = 0xFF;
  585.         WriteCivicCLUTEntry(0x7F, &entry);
  586.  
  587.         ReadCivicCLUTEntry(0xFF, &entry);            //    select entry 0xFF (foreground color) as key color
  588.         entry.alpha = 0xFF;
  589.         WriteCivicCLUTEntry(0xFF, &entry);
  590.  
  591.         err = SetVideoRectangle(&gVideoRect);        //    set the playthough rectangle
  592.  
  593.         SetVideoPlaythrough(true);                    //    turn playthrough on
  594.         gPlaythroughOn = true;
  595.  
  596.         return err;
  597.     }
  598.     else
  599.         return errMTVFeatureNotImplemented;            //    we only work on Civic for now
  600. }
  601.  
  602.  
  603. //====================================================================================================
  604. //
  605. //    Routine:        TurnVideoOff
  606. //
  607. //    Description:    Turn off the video
  608. //
  609. //    Parameters:        none
  610. //
  611. //    Returns:        error result code (negative) or noErr
  612. //
  613. //====================================================================================================
  614.  
  615. static OSErr
  616. TurnVideoOff()
  617. {
  618.     if (gHasCivic)
  619.     {
  620.         SetVideoPlaythrough(false);                    //    disable playthrough
  621.         gPlaythroughOn = false;                        //    remember that playthrough is off
  622.         return noErr;
  623.     }
  624.     else
  625.         return errMTVFeatureNotImplemented;            //    we only work on Civic for now
  626. }
  627.  
  628.  
  629. //====================================================================================================
  630. //
  631. //    Routine:        SetVideoSize
  632. //
  633. //    Description:    Set the size of the video playthrough area
  634. //
  635. //    Parameters:        size        - 1, 2, 3 or 4 for full, half, third or quarter size
  636. //
  637. //    Returns:        error result code (negative) or noErr
  638. //
  639. //====================================================================================================
  640.  
  641. static OSErr
  642. SetVideoSize(long size)
  643. {
  644.     Rect                newVideoRect;
  645.  
  646.     if ((size == 1) || (size == 2) || (size == 4))
  647.     {
  648.         newVideoRect = gVideoRect;
  649.         newVideoRect.left = newVideoRect.right - (short) kMaximumVideoWidth / size;
  650.         newVideoRect.bottom = newVideoRect.top + (short) kMaximumVideoHeight / size;
  651.         return SetVideoRectangle(&newVideoRect);
  652.     }
  653.     else
  654.         return errMTVValueOutOfRange;
  655. }
  656.  
  657.  
  658. //====================================================================================================
  659. //
  660. //    Routine:        SetVideoLeft
  661. //
  662. //    Description:    Set the left coordinate of the video playthrough area
  663. //
  664. //    Parameters:        left        - desired left of video area
  665. //
  666. //    Returns:        error result code (negative) or noErr
  667. //
  668. //====================================================================================================
  669.  
  670. static OSErr
  671. SetVideoLeft(long left)
  672. {
  673.     Rect                newVideoRect;
  674.  
  675.     if (left >= 0)
  676.     {
  677.         newVideoRect.top = gVideoRect.top;
  678.         newVideoRect.left = left;
  679.         newVideoRect.bottom = gVideoRect.bottom;
  680.         newVideoRect.right = left + (short) (gVideoRect.right - gVideoRect.left);
  681.         return SetVideoRectangle(&newVideoRect);
  682.     }
  683.     else
  684.         return errMTVValueOutOfRange;
  685. }
  686.  
  687.  
  688. //====================================================================================================
  689. //
  690. //    Routine:        SetVideoTop
  691. //
  692. //    Description:    Set the top coordinate of the video playthrough area
  693. //
  694. //    Parameters:        top        - desired top of video area
  695. //
  696. //    Returns:        error result code (negative) or noErr
  697. //
  698. //====================================================================================================
  699.  
  700. static OSErr
  701. SetVideoTop(long top)
  702. {
  703.     Rect                newVideoRect;
  704.  
  705.     if (top >= 0)
  706.     {
  707.         newVideoRect.top = top;
  708.         newVideoRect.left = gVideoRect.left;
  709.         newVideoRect.bottom = top + (short) (gVideoRect.bottom - gVideoRect.top);
  710.         newVideoRect.right = gVideoRect.right;
  711.         return SetVideoRectangle(&newVideoRect);
  712.     }
  713.     else
  714.         return errMTVValueOutOfRange;
  715. }
  716.  
  717.  
  718. //====================================================================================================
  719. //
  720. //    Routine:        SetVideoWidth
  721. //
  722. //    Description:    Set the width of the video playthrough area
  723. //
  724. //    Parameters:        width        - desired width of video area
  725. //
  726. //    Returns:        error result code (negative) or noErr
  727. //
  728. //====================================================================================================
  729.  
  730. static OSErr
  731. SetVideoWidth(long width)
  732. {
  733.     Rect                newVideoRect;
  734.  
  735.     if ((width >= kMinimumVideoWidth) && (width <= kMaximumVideoWidth))
  736.     {
  737.         newVideoRect = gVideoRect;
  738.         newVideoRect.left = newVideoRect.right - (short) width;
  739.         return SetVideoRectangle(&newVideoRect);
  740.     }
  741.     else
  742.         return errMTVValueOutOfRange;
  743. }
  744.  
  745.  
  746. //====================================================================================================
  747. //
  748. //    Routine:        SetVideoHeight
  749. //
  750. //    Description:    Set the width of the video playthrough area
  751. //
  752. //    Parameters:        width        - desired width of video area
  753. //
  754. //    Returns:        error result code (negative) or noErr
  755. //
  756. //====================================================================================================
  757.  
  758. static OSErr
  759. SetVideoHeight(long height)
  760. {
  761.     Rect                newVideoRect;
  762.  
  763.     if ((height >= kMinimumVideoHeight) && (height <= kMaximumVideoHeight))
  764.     {
  765.         newVideoRect = gVideoRect;
  766.         newVideoRect.bottom = newVideoRect.top + (short) height;
  767.         return SetVideoRectangle(&newVideoRect);
  768.     }
  769.     else
  770.         return errMTVValueOutOfRange;
  771. }
  772.  
  773.  
  774. //====================================================================================================
  775. //
  776. //    Routine:        SetVideoPlaythrough
  777. //
  778. //    Description:    Turn video playthrough on or off
  779. //
  780. //    Parameters:        on        - true to enable playthrough, false to disable playthrough
  781. //
  782. //    Returns:        error result code (negative) or noErr
  783. //
  784. //====================================================================================================
  785.  
  786. static void
  787. SetVideoPlaythrough(Boolean on)
  788. {
  789.     if (gHasCivic)
  790.     {
  791.         if (on)
  792.         {
  793.             *gSebasCLUT |= 0x80;                    //    enable playthrough
  794.             NOP();
  795.             *(long *)(gCivicBaseAddr + 0x18) = 0;    //    unfreeze video
  796.             NOP();
  797.         }
  798.         else
  799.         {
  800.             *(long *)(gCivicBaseAddr + 0x18) = 1;    //    freeze video
  801.             NOP();
  802.             *gSebasCLUT &= 0x7F;                    //    disable playthrough
  803.             NOP();
  804.         }
  805.     }
  806. }
  807.  
  808.  
  809. //====================================================================================================
  810. //
  811. //    Routine:        SetVideoRectangle
  812. //
  813. //    Description:    Set the video playthrough area
  814. //
  815. //    Parameters:        videoRect    - pointer to desired playthrough rectangle
  816. //
  817. //    Returns:        error result code (negative) or noErr
  818. //
  819. //====================================================================================================
  820.  
  821. static OSErr
  822. SetVideoRectangle(const Rect *videoRect)
  823. {
  824.     GDHandle            mainDeviceH;
  825.     VDVidInRect            vidInRect;
  826.     CntrlParam            pb;
  827.     OSErr                err;
  828.     OSErr                saveMemErr;
  829.  
  830.     if (gHasCivic)
  831.     {
  832.         mainDeviceH = LMGetMainDevice();                //    get handle to main screen device
  833.         if ((**mainDeviceH).gdRefNum == gCivicRefNum)    //    make sure main device is controlled by Civic
  834.         {
  835.             SetVideoPlaythrough(false);                    //    disable playthrough
  836.                                                     
  837.             pb.csCode = csCivicSetVidInRect;            //    specify playthrough rectangle
  838.             pb.ioCRefNum = gCivicRefNum;
  839.             vidInRect.csPage = 0;
  840.             vidInRect.csBaseAddr = 0x98765432;
  841.             vidInRect.csRect.top = videoRect->top;
  842.             vidInRect.csRect.left = videoRect->left;
  843.             vidInRect.csRect.bottom = videoRect->bottom;
  844.             vidInRect.csRect.right = videoRect->right;
  845.             *(VDVidInRect **)&pb.csParam[0] = &vidInRect;
  846.     
  847.             saveMemErr = LMGetMemErr();                    //    save value of MemErr since video driver is handle-based
  848.             err = PBControlImmed((ParmBlkPtr) &pb);        //    call Civic video driver to set playthough rectangle
  849.             LMSetMemErr(saveMemErr);                    //    restore value of MemErr since PBControl trashed it
  850.             
  851.             if (err == noErr)
  852.                 gVideoRect = *videoRect;                //    update current rectangle
  853.  
  854.             if (gPlaythroughOn)
  855.                 SetVideoPlaythrough(true);                //    reenable playthrough
  856.         }
  857.         else
  858.             err = errMTVHardwareNotAvailable;
  859.  
  860.         return err;
  861.     }
  862.     else
  863.         return errMTVFeatureNotImplemented;                //    we only work on Civic for now
  864. }
  865.  
  866.  
  867. //====================================================================================================
  868. //
  869. //    Routine:        ReadCivicCLUTEntry
  870. //
  871. //    Description:    Read an entry in the Civic CLUT
  872. //
  873. //    Parameters:        index    - CLUT index (0x00..0xFF)
  874. //                    entry    - pointer to CLUT entry to be returned
  875. //
  876. //    Returns:        nothing
  877. //
  878. //====================================================================================================
  879.  
  880. static void
  881. ReadCivicCLUTEntry(unsigned char index, CLUTEntryPtr entry)
  882. {
  883.     *gSebasAddrReg = index;
  884.     NOP();
  885.     entry->red = *gSebasDataReg;
  886.     NOP();
  887.     entry->green = *gSebasDataReg;
  888.     NOP();
  889.     entry->blue = *gSebasDataReg;
  890.     NOP();
  891.     entry->alpha = *gSebasDataReg;
  892.     NOP();
  893. }
  894.  
  895.  
  896. //====================================================================================================
  897. //
  898. //    Routine:        WriteCivicCLUTEntry
  899. //
  900. //    Description:    Write an entry in the Civic CLUT
  901. //
  902. //    Parameters:        index    - CLUT index (0x00..0xFF)
  903. //                    entry    - pointer to CLUT entry to write
  904. //
  905. //    Returns:        nothing
  906. //
  907. //====================================================================================================
  908.  
  909. static void
  910. WriteCivicCLUTEntry(unsigned char index, const CLUTEntryPtr entry)
  911. {
  912.     *gSebasAddrReg = index;
  913.     NOP();
  914.     *gSebasDataReg = entry->red;
  915.     NOP();
  916.     *gSebasDataReg = entry->green;
  917.     NOP();
  918.     *gSebasDataReg = entry->blue;
  919.     NOP();
  920.     *gSebasDataReg = entry->alpha;
  921.     NOP();
  922. }
  923.  
  924.  
  925. //====================================================================================================
  926. //
  927. //    Routine:        SetTVChannel
  928. //
  929. //    Description:    Set the television channel
  930. //
  931. //    Parameters:        channel        - channel to select
  932. //
  933. //    Returns:        error result code (negative) or noErr
  934. //
  935. //====================================================================================================
  936.  
  937. #define    kFirstChannel    2
  938. #define    kNumChannels    68
  939.  
  940. static OSErr
  941. SetTVChannel(long channel)
  942. {
  943.     static const long channelFreq[kNumChannels] =        //    table of U.S. channel frequencies
  944.     {
  945.         0x034B0C50, 0x03A699D0, 0x04022750, 0x049ABDD0,
  946.         0x04F64B50, 0x0A721A50,    0x0ACDA7D0, 0x0B293550,
  947.         0x0B84C2D0, 0x0BE05050, 0x0C3BDDD0, 0x0C976B50,
  948.         0x1C16B450, 0x1C7241D0, 0x1CCDCF50, 0x1D295CD0,
  949.         0x1D84EA50, 0x1DE077D0, 0x1E3C0550, 0x1E9792D0,
  950.         0x1EF32050, 0x1F4EADD0, 0x1FAA3B50, 0x2005C8D0,
  951.         0x20615650, 0x20BCE3D0, 0x21187150, 0x2173FED0,
  952.         0x21CF8C50, 0x222B19D0, 0x2286A750, 0x22E234D0,
  953.         0x233DC250, 0x23994FD0, 0x23F4DD50, 0x24506AD0,
  954.         0x24ABF850, 0x250785D0, 0x25631350, 0x25BEA0D0,
  955.         0x261A2E50, 0x2675BBD0, 0x26D14950, 0x272CD6D0,
  956.         0x27886450, 0x27E3F1D0, 0x283F7F50, 0x289B0CD0,
  957.         0x28F69A50, 0x295227D0, 0x29ADB550, 0x2A0942D0,
  958.         0x2A64D050, 0x2AC05DD0, 0x2B1BEB50, 0x2B7778D0,
  959.         0x2BD30650, 0x2C2E93D0, 0x2C8A2150, 0x2CE5AED0,
  960.         0x2D413C50, 0x2D9CC9D0, 0x2DF85750, 0x2E53E4D0,
  961.         0x2EAF7250, 0x2F0AFFD0, 0x2F668D50, 0x2FC21AD0
  962.     };
  963.  
  964.     if (gHasTVTuner)
  965.     {
  966.         if ((channel >= kFirstChannel) && (channel <= kFirstChannel + kNumChannels - 1))
  967.         {
  968.             return errMTVFeatureNotImplemented;
  969.         }
  970.         else
  971.             return errMTVValueOutOfRange;
  972.     }
  973.     else
  974.         return errMTVHardwareNotAvailable;
  975. }
  976.  
  977.  
  978. //====================================================================================================
  979. //
  980. //    Routine:        DumpCLUT
  981. //
  982. //    Description:    Dump the video hardware CLUT to MacsBug
  983. //
  984. //    Parameters:        none
  985. //
  986. //    Returns:        error result code (negative) or noErr
  987. //
  988. //====================================================================================================
  989.  
  990. static OSErr
  991. DumpCLUT()
  992. {
  993.     CLUTEntry        entry;
  994.     unsigned short    index;
  995.  
  996.     if (gHasCivic)
  997.     {
  998.         dcmdDrawLine("\pDisplaying Civic CLUT");
  999.  
  1000.         for (index = 0x00; index <= 0xFF; ++index)
  1001.         {
  1002.             ReadCivicCLUTEntry(index, &entry);
  1003.             PutPStr("\p Entry ");
  1004.             PutUHexZ(index, 2);            PutPStr("\p: (");
  1005.             PutUHexZ(entry.red, 2);        PutPStr("\p, ");
  1006.             PutUHexZ(entry.green, 2);    PutPStr("\p, ");
  1007.             PutUHexZ(entry.blue, 2);    PutPStr("\p, ");
  1008.             PutUHexZ(entry.alpha, 2);    PutPStr("\p)");
  1009.             PutLine();
  1010.         }
  1011.  
  1012.         return noErr;
  1013.     }
  1014.     else
  1015.     {
  1016.         dcmdDrawLine("\pUnable to dump CLUT");
  1017.         return errMTVFeatureNotImplemented;                //    we only work on Civic for now
  1018.     }
  1019. }
  1020.  
  1021.  
  1022. //====================================================================================================
  1023. //
  1024. //    Routine:        GetDriverRefNum
  1025. //
  1026. //    Description:    Find the refnum of the driver with the given name
  1027. //
  1028. //    Parameters:        driverName    - name of desired driver
  1029. //
  1030. //    Returns:        driver refnum or 0 if not found
  1031. //
  1032. //====================================================================================================
  1033.  
  1034. static short
  1035. GetDriverRefNum(const StringPtr driverName)
  1036. {
  1037.     DCtlHandle            dceH;
  1038.     DCtlHandle *        unitTableBase = (DCtlHandle *) LMGetUTableBase();
  1039.     DRVRHeaderPtr        driverHdrP;
  1040.     unsigned short        unitTableEntries = LMGetUnitTableEntryCount();
  1041.     unsigned short        unitNum;
  1042.  
  1043.     for (unitNum = 0; unitNum < unitTableEntries; ++unitNum)
  1044.     {
  1045.         dceH = unitTableBase[unitNum];
  1046.         if (dceH != nil)
  1047.         {
  1048.             if ((**dceH).dCtlFlags & dRAMBasedMask)
  1049.                 driverHdrP = (DRVRHeaderPtr) (*(Handle)((**dceH).dCtlDriver));
  1050.             else
  1051.                 driverHdrP = (DRVRHeaderPtr) ((**dceH).dCtlDriver);
  1052.             if (EqualString(driverName, driverHdrP->drvrName, false, false))
  1053.                 return ~unitNum;
  1054.         }
  1055.     }
  1056.     
  1057.     return 0;
  1058. }
  1059.